#include "AIC32.h"
#include "main.h"
#include "leds.h"

void IIR_filter_run(void);

void IIR_InBuff_add(float value);

float IIR_OutBuff_GetEnd();

float IIR_filter(float x);

//extern float IIR_output[IIR_SIZE];

/****************端口宏定??*****************/
#define LuYin GpioDataRegs.GPADAT.bit.GPIO12
#define LuYin_ST GpioDataRegs.GPADAT.bit.GPIO13
#define BoYin GpioDataRegs.GPADAT.bit.GPIO14

/**
 * ?????????????define???1?????????????????
 */
#define SIMPLERATE_8K    0
#define SIMPLERATE_8K021 0
#define SIMPLERATE_32K   0
#define SIMPLERATE_44k1  0
#define SIMPLERATE_48K   1

#define DATA_SIZE 1024

// 接收数据缓冲区，用来做波形观察
// 数据定义在片外SARAM上，片内可能不够存
#pragma DATA_SECTION(aic23_recdata, "ZONE7DATA");
volatile int aic23_recdata[DATA_SIZE];


Uint16 AIC23Write(int Address, int Data);

interrupt void ISRMcbspRece(void);

/**
 * IIC初始化，IIC用于操控AIC23的寄存器，控制音频芯片
 */
void I2CA_Init(void)
{
  // Initialize I2C
  I2caRegs.I2CSAR = 0x001A;    // Slave address - EEPROM control code

#if (CPU_FRQ_150MHZ)             // Default - For 150MHz SYSCLKOUT
  I2caRegs.I2CPSC.all = 14;   // Prescaler - need 7-12 Mhz on module clk (150/15 = 10MHz)
#endif
#if (CPU_FRQ_100MHZ)             // For 100 MHz SYSCLKOUT
  I2caRegs.I2CPSC.all = 9;	    // Prescaler - need 7-12 Mhz on module clk (100/10 = 10MHz)
#endif

  I2caRegs.I2CCLKL = 100;      // NOTE: must be non zero
  I2caRegs.I2CCLKH = 100;      // NOTE: must be non zero
  I2caRegs.I2CIER.all = 0x24;    // Enable SCD & ARDY interrupts

//   I2caRegs.I2CMDR.all = 0x0020;	// Take I2C out of reset
  I2caRegs.I2CMDR.all = 0x0420;  // Take I2C out of reset		//zq
  // Stop I2C when suspended

  I2caRegs.I2CFFTX.all = 0x6000;  // Enable FIFO mode and TXFIFO
  I2caRegs.I2CFFRX.all = 0x2040;  // Enable RXFIFO, clear RXFFINT,

  return;
}


void AIC23_Init()
{
  Uint32 i;
  //Gpio复用设置
  InitMcbspaGpio();
  InitI2CGpio();
  //IIC初始化
  I2CA_Init();
  //Mcbsp初始化，多通道串口，用于传输音频数据
  InitMcbspa();
  DELAY_US(10000);
  // 0x0F 0b00001111 复位寄存器，写0时复位
  AIC23Write(0x0f, 0x00);
  DELAY_US(10000);
  // 0x00 0b00000000 左输入通道音量控制寄存器，设置为最小输入增益，-34.5DB ，这个不重要，调到合适的位置就行
  AIC23Write(0x00, 0x00);
  DELAY_US(10000);
  // 0x01 0b00000001 右边输入通道音量控制寄存器，设置为最小输入增益，-34.5DB ，这个不重要，调到合适的位置就行
  AIC23Write(0x01, 0x00);
  DELAY_US(10000);
  // 0x02 0b00000010 左声道耳机音量控制器：零点检测-关闭；增益：拉满，+6dB ，跟上面一样，数值合适就行
  AIC23Write(0x02, 0x7f);
  DELAY_US(10000);
  // 0x03 0b00000011 右边声道耳机音量控制器：零点检测-关闭；增益：拉满，+6dB ，跟上面一样，数值合适就行
  AIC23Write(0x03, 0x7f);
  DELAY_US(10000);
  // 0x04 0b00000100 模拟音频路径控制：打开DAC，输入通道：麦克风输入（共有两种模式，麦克风输入跟线输入）
  AIC23Write(0x04, 0x14);
  DELAY_US(10000);
  // 0x05 0b00000101 数字音频路径控制：写0禁用
  AIC23Write(0x05, 0x00);
  DELAY_US(10000);
  // 0x06 0b00000110 电源控制寄存器：写0打开所有电源
  AIC23Write(0x06, 0x00);
  DELAY_US(10000);
  // 0x07 0b00000111 数字音频接口格式寄存器：主机模式，DSP格式，帧同步后接两个数据字，字长16位
  AIC23Write(0x07, 0x43);
  DELAY_US(10000);
  // 0x08 0b00001000 采样率控制寄存器 统一采用USB模式，采样率与寄存器值的对应关系如下:
  AIC23Write(0x08, 0x0D);
  DELAY_US(10000);
//  AIC23Write(0x09, 0x01);
#if SIMPLERATE_8K
  AIC23Write(0x08, 0x0D);        //8khz
  DELAY_US(10000);
#endif
#if SIMPLERATE_8K021

  AIC23Write(0x08, 0x2F);        //8.021khz
  DELAY_US(10000);
#endif
#if SIMPLERATE_32K
  DELAY_US(10000);
  AIC23Write(0x08, 0x19);        //32khz
#endif
#if SIMPLERATE_44k1
  DELAY_US(10000);
  AIC23Write(0x08, 0x23);//44.1khz
#endif
#if SIMPLERATE_48K
  DELAY_US(10000);
  AIC23Write(0x08, 0x01);       //48khz
#endif
  DELAY_US(10000);
  // 激活数字接口激活
  AIC23Write(0x09, 0x01);
  DELAY_US(10000);    //AIC23Init

  //中断设置
  EALLOW;  // This is needed to write to EALLOW protected registers
  PieVectTable.MRINTA = &ISRMcbspRece;
  EDIS;   // This is needed to disable write to EALLOW protected registers
  PieCtrlRegs.PIECTRL.bit.ENPIE = 1;   // Enable the PIE block
  PieCtrlRegs.PIEIER6.bit.INTx5 = 1;     // Enable PIE Group 6, INT 5
  IER |= M_INT6;                            // Enable CPU INT6

  // 由于外部saram在dsp复位时并不会清空数据，所以手动清空一下
  for (i = 0; i < DATA_SIZE; ++i)
  {
    aic23_recdata[i] = 0;
  }
}

/**
 * AIC23寄存器写操作函数
 * @param Address 寄存器地址
 * @param Data 寄存器值
 * @return
 */
Uint16 AIC23Write(int Address, int Data)
{


  if (I2caRegs.I2CMDR.bit.STP == 1)
  {
    return I2C_STP_NOT_READY_ERROR;
  }

  // Setup slave address
  I2caRegs.I2CSAR = 0x1A;

  // Check if bus busy
  if (I2caRegs.I2CSTR.bit.BB == 1)
  {
    return I2C_BUS_BUSY_ERROR;
  }

  // Setup number of bytes to send
  // MsgBuffer + Address
  I2caRegs.I2CCNT = 2;
  I2caRegs.I2CDXR = Address << 1;
  I2caRegs.I2CDXR = Data;
  // Send start as master transmitter
  I2caRegs.I2CMDR.all = 0x6E20;
  return I2C_SUCCESS;

}

void AIC23_OUTPUT_LEFT(int16 value)
{
  McbspaRegs.DXR1.all = value; // 输出左声道数??
}

void AIC23_OUTPUT_RIGHT(int16 value)
{
  McbspaRegs.DXR2.all = value; // 输出右声道数??
}

void AIC23_OUTPUT(int16 value)
{
  AIC23_OUTPUT_LEFT(value);
  AIC23_OUTPUT_RIGHT(value);
}

int16 AIC23_INTPUT_LEFT()
{
  return McbspaRegs.DRR1.all;
}

int16 AIC23_INTPUT_RIGHT()
{
  return McbspaRegs.DRR2.all;
}

int16 AIC23_INTPUT_AVG()
{
  int temp1, temp2;
  temp1 = McbspaRegs.DRR1.all;
  temp2 = McbspaRegs.DRR2.all;
  return (temp1 + temp2);
}

volatile unsigned int index = 0;

volatile Uint32 index_rec = 0;

volatile Uint16 iir_mode = 1; //0滤波器打开 1滤波器关闭

volatile int outputvalue = 0;

interrupt void ISRMcbspRece(void)
{
  // 读取音频采样值
  int value = AIC23_INTPUT_AVG();
  // 因为每次采样操作会触发两次中断，所以手动调整一下代码让他每两次中断处理一次滤波，iir滤波器的采样率是严格规定的
  if (index % 2 == 0)
  {
    //如果滤波器打开，则对value进行滤波处理，否则不处理
    if (iir_mode == 0)
    {
      value = (int) IIR_filter((float) value);
    }
    //保存数据
    if (index_rec < DATA_SIZE)
    {
      aic23_recdata[index_rec++] = value;
    } else
    {
      index_rec = 0;
      aic23_recdata[index_rec++] = value;
    }
    // 这个outputvalue是方便查看数据用的，现在没用了
    outputvalue = value;
    // 输出，左右声道好像有点问题
    AIC23_OUTPUT_LEFT(value);
  }
  //led灯翻转，因为翻转会产生方波，调试采样率的时候用这个灯的波形去测进中断的频率，也就是测采样率
  LED9_TOGGLE;
  index++;
  //清空标志位
  PieCtrlRegs.PIEACK.all = 0x0020;
}
